/*************************************************************/
//2014.03.06修改版
/*************************************************************/
#include "fm175xx.h"
#include "type_a.h"
#include "stdio.h"
#include "string.h"
#include "stm32f10x.h"

//ATQA只有两个字节
//UID却是4个字节加一个BCC校验值所以针对7字节UID防碰撞时就需要最多15字节的UID来存放
//SAK是一个字节的SAK+CRC_A(2字节)
uint8_t picc_atqa[2],picc_uid[15],picc_sak[3];

/***************************************************************************************
名称： 	TypeA_Request																	
功能： 	TypeA_Request卡片寻卡															
输入：																				     			    			     													       								 												
输出：	pTagType[0],pTagType[1] =ATQA                                         						
       	1: 应答正确                                                              	
	 		0: 应答错误																
****************************************************************************************/
uint8_t TypeA_Request(uint8_t *pTagType)
{
	unsigned char result,send_buff[1],rece_buff[2];
	unsigned int  rece_bitlen;
	
	Clear_BitMask(TxModeReg,0x80);		//关闭TX CRC
	Clear_BitMask(RxModeReg,0x80);		//关闭RX CRC
	Set_BitMask(RxModeReg, 0x08);		//关闭位接收
	Clear_BitMask(Status2Reg,0x08);
	FM175xx_Write_Register(BitFramingReg,0x07);
   	FM175xx_SetTimer(1);
	Clear_FIFO();
	
	send_buff[0] = 0x26;
	result = FM175xx_Comm(Transceive,send_buff,1,rece_buff,&rece_bitlen);
#if 0	
	if ((result == 1) && (rece_bitlen == 2 * 8))
	{    
		*pTagType     = rece_buff[0];
		*(pTagType+1) = rece_buff[1];
	}
#else
	if(rece_bitlen != 2 * 8)		//ERR 
		result = 0;
	
	if(result == 1)
	{    
		*pTagType     = rece_buff[0];
		*(pTagType+1) = rece_buff[1];
	}
#endif

	return result;
}
/****************************************************************************************
名称： 	TypeA_WakeUp																	
功能： 	TypeA_WakeUp卡片寻卡															
输入：																				      			    			     									       								 												
输出：	pTagType[0],pTagType[1] =ATQA                                         							
       	1: 应答正确                                                              	
	 	0: 应答错误																
****************************************************************************************/
unsigned char TypeA_WakeUp(unsigned char *pTagType)
{
	unsigned char   result,send_buff[1],rece_buff[2];
	unsigned int   rece_bitlen;  
	Clear_BitMask(TxModeReg,0x80);		//关闭TX CRC
	Clear_BitMask(RxModeReg,0x80);		//关闭RX CRC
	Set_BitMask(RxModeReg, 0x08);		//不接收小于4bit的数据
	Clear_BitMask(Status2Reg,0x08);
	FM175xx_Write_Register(BitFramingReg,0x07);
 	send_buff[0] = 0x52;
   	FM175xx_SetTimer(1);
	Clear_FIFO();
	result = FM175xx_Comm(Transceive,send_buff,1,rece_buff,&rece_bitlen);

	if ((result == 1) && (rece_bitlen == 2*8))
	{    
		*pTagType     = rece_buff[0];
		*(pTagType+1) = rece_buff[1];
	}
	return result;
}
/****************************************************************************************
名称：TypeA_Anticollision																
功能：TypeA_Anticollision卡片防冲突													
输入：selcode = 0x93，0x95，0x97														      			    			     													       								 												
输出：	pSnr[0],pSnr[1],pSnr[2],pSnr[3]pSnr[4] =UID                            							
       	1: 应答正确                                                              	
	 	0: 应答错误																
****************************************************************************************/
unsigned char TypeA_Anticoll()
{

	return 0;
}
/****************************************************************************************
名称：TypeA_Anticollision																
功能：TypeA_Anticollision卡片防冲突													
输入：selcode = 0x93，0x95，0x97														      			    			     													       								 												
输出：	pSnr[0],pSnr[1],pSnr[2],pSnr[3]pSnr[4] =UID                            							
       	1: 应答正确                                                              	
	 	0: 应答错误																
****************************************************************************************/
unsigned char TypeA_Anticollision(unsigned char selcode,unsigned char *pSnr)
{
    unsigned char result,i,send_buff[2],rece_buff[5];
    /*volatile*/ unsigned int rece_bitlen;
	Clear_BitMask(TxModeReg,0x80);
	Clear_BitMask(RxModeReg,0x80);
    Clear_BitMask(Status2Reg,0x08);
    FM175xx_Write_Register(BitFramingReg,0x00);
    Clear_BitMask(CollReg,0x80);
 
    send_buff[0] = selcode;
    send_buff[1] = 0x20;             //NVB
    FM175xx_SetTimer(1);
	Clear_FIFO();
    result = FM175xx_Comm(Transceive,send_buff,2,rece_buff,&rece_bitlen);

    if (result == 1)
    {
    	 for (i=0; i<5; i++)
         {   
             *(pSnr+i)  = rece_buff[i];
         }
         if (pSnr[4] != (pSnr[0]^pSnr[1]^pSnr[2]^pSnr[3]))     //UID0、UID1、UID2、UID3、BCC(校验字节)
    		result = 0;    
    }
  return result;
}
/****************************************************************************************
名称： 	TypeA_Select																	
功能： 	TypeA_Select卡片选卡															
输入：	selcode =0x93，0x95，0x97														
      	pSnr[0],pSnr[1],pSnr[2],pSnr[3]pSnr[4] =UID 			    			     	       								 												
输出：  pSak[0],pSak[1],pSak[2] =SAK			                            							
      	1: 应答正确                                                              	
		0: 应答错误																
****************************************************************************************/
unsigned char TypeA_Select(unsigned char selcode,unsigned char *pSnr,unsigned char *pSak)
{
    unsigned char result,i,send_buff[7],rece_buff[5];
    unsigned int rece_bitlen;
	FM175xx_Write_Register(BitFramingReg,0x00);
  	Set_BitMask(TxModeReg,0x80);      //打开TX CRC
	Set_BitMask(RxModeReg,0x80);        //打开接收RX 的CRC校验
    Clear_BitMask(Status2Reg,0x08);
	
	send_buff[0] = selcode;        //SEL
    send_buff[1] = 0x70;         //NVB
    
    for (i=0; i<5; i++)
    {
    	send_buff[i+2] = *(pSnr+i);
    }
   	
	FM175xx_SetTimer(1);
	Clear_FIFO();
    result = FM175xx_Comm(Transceive,send_buff,7,rece_buff,&rece_bitlen);
    
	if(rece_bitlen / 8 == 0)
		return 0;
	
    if (result == 1)
		*pSak=rece_buff[0]; 
	
    return result;
}
/***************************************************************************************
名称： 	TypeA_Halt																		
功能： 	TypeA_Halt卡片停止																
输入：																			      			    			     											       								 												
输出：	1: 应答正确                                                              	
	 	0: 应答错误																
****************************************************************************************/
unsigned char TypeA_Halt(void)
{
    unsigned char   result,send_buff[2],rece_buff[1];
	unsigned int   rece_bitlen;
    send_buff[0] = 0x50;
    send_buff[1] = 0x00;
   
   	FM175xx_Write_Register(BitFramingReg,0x00);
  	Set_BitMask(TxModeReg,0x80);
	Set_BitMask(RxModeReg,0x80);
    Clear_BitMask(Status2Reg,0x08);
	FM175xx_SetTimer(1);
	Clear_FIFO();
    result = FM175xx_Comm(Transmit,send_buff,2,rece_buff,&rece_bitlen);
    return result;
}
/****************************************************************************************
名称： TypeA_Read_Request																
功能： TypeA_Read_Request 卡片激活														
输入：																				      			    			     													       								 												
输出：	是否TypeA_Read_Request成功											
****************************************************************************************/
unsigned char TypeA_Read_Request(void)
{
	unsigned char tagtype[2];
	return TypeA_Request(tagtype);
}
/****************************************************************************************
名称： TypeA_Read_AntiColl																
功能： TypeA_Read_AntiColl 卡片激活														
输入：																				      			    			     													       								 												
输出：											
****************************************************************************************/

u8 UID[5];
u8 Send_Buf[20];
u8 Recv_Buf[20];

void Save_UID(u8 row, u8 col, u8 length)
{
	u8 i;
	u8 tmp;
	u8 tmp1;
	
	if((row==0x00) && (col==0x00))
	{
		for(i=0; i<length; i++)
		{
			UID[i] = Recv_Buf[i];
		}
	}
	else
	{
		tmp = Recv_Buf[0];
		tmp1 = UID[row-1];
		switch(col)
		{
			case 0: tmp1 = 0x00; row = row + 1; break;
			case 1: tmp = tmp & 0xFE; tmp1 = tmp1 & 0x01; break;
			case 2: tmp = tmp & 0xFC; tmp1 = tmp1 & 0x03; break;
			case 3:	tmp = tmp & 0xF8; tmp1 = tmp1 & 0x07; break;
			case 4:	tmp = tmp & 0xF0; tmp1 = tmp1 & 0x0F; break;
			case 5:	tmp = tmp & 0xE0; tmp1 = tmp1 & 0x1F; break;
			case 6:	tmp = tmp & 0xC0; tmp1 = tmp1 & 0x3F; break;
			case 7:	tmp = tmp & 0x80; tmp1 = tmp1 & 0x7F; break;
			default: break;
		}

		UID[row-1] = tmp1 | tmp;
		for(i=1; i<length; i++)
		{
			UID[row-1+i] = Recv_Buf[i];
		}
	}
}

u8 Check_UID(void)
{
	u8 tmp;
	u8 i;
	
	tmp = 0x00;
	for(i=0; i<5; i++)
	{
		tmp ^= UID[i];
	}

	if(tmp==0)
		return TRUE;
	else
		return FALSE;
}

void Set_BitFraming(u8 row, u8 col)
{
	switch(row)
	{
		case 0:		Send_Buf[1] = 0x20; break;
		case 1:		Send_Buf[1] = 0x30; break;
		case 2:		Send_Buf[1] = 0x40; break;
		case 3:		Send_Buf[1] = 0x50; break;
		case 4:		Send_Buf[1] = 0x60; break;
		default:	break;
	}

	switch(col)
	{
		case 0:		FM175xx_Write_Register(BitFramingReg,0x00); break;
		case 1:		FM175xx_Write_Register(BitFramingReg,0x11); Send_Buf[1] = (Send_Buf[1] | 0x01); break;
		case 2:		FM175xx_Write_Register(BitFramingReg,0x22); Send_Buf[1] = (Send_Buf[1] | 0x02); break;
		case 3:		FM175xx_Write_Register(BitFramingReg,0x33); Send_Buf[1] = (Send_Buf[1] | 0x03); break;
		case 4:		FM175xx_Write_Register(BitFramingReg,0x44); Send_Buf[1] = (Send_Buf[1] | 0x04); break;
		case 5:		FM175xx_Write_Register(BitFramingReg,0x55); Send_Buf[1] = (Send_Buf[1] | 0x05); break;
		case 6:		FM175xx_Write_Register(BitFramingReg,0x66); Send_Buf[1] = (Send_Buf[1] | 0x06); break;
		case 7:		FM175xx_Write_Register(BitFramingReg,0x77); Send_Buf[1] = (Send_Buf[1] | 0x07); break;
		default:	break;
	}
}

u8 TypeA_Read_AntiColl(u8 select_code)
{
    unsigned char result = 0,i = 0,tmp = 0,row = 0,pre_row = 0,col = 0;
    unsigned int rece_bitlen,RecvLen = 0;

	Clear_BitMask(TxModeReg,0x80);
	Clear_BitMask(RxModeReg,0x80);
    Clear_BitMask(Status2Reg,0x08);
    FM175xx_Write_Register(BitFramingReg,0x00);
    Clear_BitMask(CollReg,0x80);
 
	Send_Buf[0] = select_code;
	Send_Buf[1] = 0x20;					//NVB
	
    FM175xx_SetTimer(1);
	Clear_FIFO();
    result = FM175xx_Comm(Transceive,Send_Buf,2,Recv_Buf,&rece_bitlen);

	while(1)
	{
		if(result != 1)
			return 0;

		if(rece_bitlen == 0)
			return 0;
		
		if(rece_bitlen % 8 != 0)
		{
			RecvLen = rece_bitlen / 8 + 1;
		}
		else
		{
			RecvLen = rece_bitlen / 8;
		}
		
		Save_UID(row, col, RecvLen);
		
		tmp = FM175xx_Read_Register(ErrorReg);
		
		tmp = tmp & 0x08;					//0x00001000   = 0x08
		if(tmp == 0x00)
		{
			tmp = Check_UID();

			if(tmp == 0)
			{
				return 0;
			}
			return 1;
		}
		else
		{
			tmp = FM175xx_Read_Register(CollReg);
			
			row = tmp / 8;
			col = tmp % 8;
			
			//RevBuffer[0] = RF_CMD_ANTICOL;
			
			Set_BitFraming(row + pre_row, col);
			
			pre_row = pre_row + row;
			for(i = 0; i < pre_row + 1; i++)
			{
				Send_Buf[i + 2] = UID[i];
			}

			if(col != 0x00)
			{
				row = pre_row + 1;
			}
			else
			{
				row = pre_row;
			}

			result = FM175xx_Comm(Transceive,Send_Buf,row + 2,Recv_Buf,&rece_bitlen);
		}
	}
}

/****************************************************************************************
名称： TypeA_Read_Activate																
功能： TypeA_Read_Activate 卡片激活														
输入：																				      			    			     													       								 												
输出：											
****************************************************************************************/
unsigned char TypeA_Read_Activate(uint8_t *csn)
{
	u8 select_code,CascadeLevel = 0,index = 0,sak;

	do
	{
		select_code = 0x93 + (CascadeLevel * 2);
		if(TypeA_Read_AntiColl(select_code) != 1)
			return 0;

		if(TypeA_Select(select_code, UID, &sak) != 1)
			return 0;

		CascadeLevel++;
		if(sak&0x04)
		{
			memcpy(csn+index, &UID[1], 3);
			index += 3;
		}
		else
		{
			memcpy(csn+index, &UID[0], 4);
			index += 4;
		}
	}while((sak&0x04)&&(CascadeLevel<3));
	
	if((CascadeLevel>=3)&&(sak&0x04))
	{
		return 0;
	}

	return 1;
}
/****************************************************************************************
名称： TypeA_Card_Detect																
功能： TypeA_Card_Detect 卡片激活														
输入：
输出：	CSN需要10字节的最大容量,4字节卡会在前填充4字节,8字节卡,直接全卡号											
****************************************************************************************/
unsigned char TypeA_Card_Detect(uint8_t *csn)
{
	u8 err = 0;
	while(err < 2)		//实际使用中发现,REQ2次比较稳定
	{
		if(TypeA_Read_Request() == 1)
			break;
		
		err++;
	}
	
	if(err == 2)
		return 0;
	
	err = 0;
	while(err < 2)		//保持稳定做法,实际效果未知
	{
		if(TypeA_Read_Activate(csn) == 1)
			break;
		
		err++;
	}
	
	if(err == 2)
		return 0;
	
	return 1;
}
/****************************************************************************************
名称：TypeA_CardActive																
功能：TypeA_CardActive卡片激活														
输入：																				      			    			     													       								 												
输出：	pTagType[0],pTagType[1] =ATQA 											 	
	    pSnr[0],pSnr[1],pSnr[2],pSnr[3]pSnr[4] =UID 		                   		
	    pSak[0],pSak[1],pSak[2] =SAK			                            							
       	1: 应答正确                                                              	
	 	0: 应答错误																
****************************************************************************************/
static void Type_RF_Dely(uint32_t _100us)
{
	uint32_t i;
	for ( ; 0 != _100us; _100us--)
	{
		for(i = 0; i < 550; i++);
	}
}

unsigned char TypeA_CardActive(unsigned char *pTagType,unsigned char *pSnr,unsigned char *pSak)
{
	FM175xx_SoftReset();
	FM175xx_Set_Rf(OPEN_ALL_TX);	
	FM175xx_ConfigISOType(ISO_Cfg_TYPE_A);
	Type_RF_Dely(20);
	
	if(TypeA_Request(pTagType) != 1)				//寻卡 Standard	 send request command Standard mode	
		return 0;

	switch ((pTagType[0]&0xC0))        			//M1卡,ID号只有4位
	{
		case 0x00:
			{
				if(TypeA_Anticollision(0x93,pSnr) != 1)
					return 0;		

				if(TypeA_Select(0x93,pSnr,pSak) != 1)
					return 0;				
			}
			break;
		case 0x40:
			{
				if(TypeA_Anticollision(0x93,pSnr) != 1)
					return 0;

				if(TypeA_Select(0x93,pSnr,pSak) != 1)
					return 0;

				if(TypeA_Anticollision(0x95,pSnr+5) != 1)
					return 0;

				if(TypeA_Select(0x95,pSnr+5,pSak+1) != 1)
					return 0;
			}
			break;
		case 0x80:
			{
				if(TypeA_Anticollision(0x93,pSnr) != 1)
					return 0;

				if(TypeA_Select(0x93,pSnr,pSak) != 1)
					return 0;

				if(TypeA_Anticollision(0x95,pSnr+5) != 1)
					return 0;

				if(TypeA_Select(0x95,pSnr+5,pSak+1) != 1)
					return 0;

				if(TypeA_Anticollision(0x97,pSnr+10) != 1)
					return 0;

				if(TypeA_Select(0x97,pSnr+10,pSak+2) != 1)
					return 0;
			}
			break;
		default:
			break;
	}
	return 1;
}
/****************************************************************************************
名称：ReadCard_TypeBActive																
功能：ReadCard_TypeBActive卡片激活														
输入：																				      			    			     													       								 												
输出：															
****************************************************************************************/
unsigned char ReadCard_TypeAActive(unsigned char *csn,unsigned char *csn_len)
{
	if(TypeA_CardActive(picc_atqa,picc_uid,picc_sak))
	{
		*csn_len = 4;
		memcpy(csn,picc_uid,4);
		return 1;
	}
	return 0;
}
/****************************************************************************************
名称： TypeA_RF_Open																
功能： TypeA_RF_Open打开A类卡天线(无Dely模式)														
输入： 
输出： 
****************************************************************************************/
void TypeA_RF_Open(void)
{
	FM175xx_SoftReset();
	FM175xx_Set_Rf(OPEN_ALL_TX);
	FM175xx_ConfigISOType(ISO_Cfg_TYPE_A);	
}
/****************************************************************************************
名称： TypeA_RF_Close																
功能： TypeA_RF_Close打开A类卡天线(无Dely模式)														
输入： 
输出： 
****************************************************************************************/
void TypeA_RF_Close(void)
{
	FM175xx_Set_Rf(CLOSE_ALL_TX);
}
